/**
 ** @author:	   浓咖啡
 ** @date:	   2017.3.29
 ** @brief:      pcap库支持程序
 */

#include <pcap.h>
#include "cap_manager.h"

static pcap_t *device;

static bool pcap_init(char *dev_str, char *filter_str)
{
    char errBuf[PCAP_ERRBUF_SIZE];

    if(NULL == dev_str){
        /* get a device */
        dev_str = pcap_lookupdev(errBuf);
    }

    if(dev_str){
#ifdef DEBUG_ON
        printf("device is: %s\n", dev_str);
        printf("filter is: %s\n\n", filter_str);
#endif
    }else{
        printf("error: %s\n", errBuf);
        return fail;
    }

    /* open a device, wait until a packet arrives */
    device = pcap_open_live(dev_str, 65535, 1, 0, errBuf);
    if(!device){
        printf("error: pcap_open_live(): %s\n", errBuf);
        return fail;
    }

    /* construct a filter */
    struct bpf_program filter;
    pcap_compile(device, &filter, filter_str, 1, 0);
    pcap_setfilter(device, &filter);

    return success;
}

static void get_packet(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
{
    code(packet, pkthdr->len);
}

static void pcap_start()
{
    /* wait loop forever */
    int id = 0;
    pcap_loop(device, -1, get_packet, (u_char*)&id);
}

static void close_capture()
{
    pcap_close(device);
}

static cap_opt_t pcap_opt = {
    .name = "pcap",
    .cap_init = pcap_init,
    .start_cap = pcap_start,
    .close_cap = close_capture,
};

int init_pcap(void)
{
    return register_cap_opt(&pcap_opt);
}
